﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string>
#include <unordered_map>

using namespace std;

int main()
{
	int n;
	cin >> n;
	unordered_map<string, int> mp;
	int ret = 0;
	while (n--)
	{
		string a, b;
		cin >> a >> b;
		//<城市前两个字符拼接州名， 出现次数>
		//截取城市名前两个字符
		a = a.substr(0, 2);
		if (a == b)
		{
			//城市前两个字符和城市所在州名相同
			//不符合题目规定“来自不同的州”直接continue
			continue;
		}
		//一对统计一次，只有在一对符合要求的第二个出现的数据才统计
		//先查后存,避免当前数据与自身匹配
		ret += mp[b + a];
		mp[a + b]++;
	}
	cout << ret << endl;
	return 0;
}




struct file {
	...
		struct inode* f_inode; /* cached value */
	const struct file_operations* f_op;
	...
		atomic_long_t f_count; // 表⽰打开⽂件的引⽤计数，如果有多个⽂件指针指向
	//它，就会增加f_count的值。
		unsigned int f_flags; // 表⽰打开⽂件的权限
	fmode_t f_mode; // 设置对⽂件的访问模式,例如：只读，只写等。所有
	//的标志在头⽂件<fcntl.h> 中定义
		loff_t f_pos; // 表⽰当前读写⽂件的位置
	...
} __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */


struct file_operations {
	struct module* owner;
	//指向拥有该模块的指针；
	loff_t(*llseek) (struct file*, loff_t, int);
	//llseek ⽅法⽤作改变⽂件中的当前读/写位置, 并且新位置作为(正的)返回值.
	ssize_t(*read) (struct file*, char __user*, size_t, loff_t*);
	//⽤来从设备中获取数据. 在这个位置的⼀个空指针导致 read 系统调⽤以 -
	EINVAL("Invalid argument") //失败.⼀个⾮负返回值代表了成功读取的字节数(返回值是⼀个
		"signed size" //类型, 常常是⽬标平台本地的整数类型).
		ssize_t(*write) (struct file*, const char __user*, size_t, loff_t*);
	//发送数据给设备. 如果 NULL, -EINVAL 返回给调⽤ write 系统调⽤的程序. 如果⾮负, 返
	//回值代表成功写的字节数.
		ssize_t(*aio_read) (struct kiocb*, const struct iovec*, unsigned long,
			loff_t);
	//初始化⼀个异步读 -- 可能在函数返回前不结束的读操作.
	ssize_t(*aio_write) (struct kiocb*, const struct iovec*, unsigned long,
		loff_t);
	//初始化设备上的⼀个异步写.
	int (*readdir) (struct file*, void*, filldir_t);
	//对于设备⽂件这个成员应当为 NULL; 它⽤来读取⽬录, 并且仅对**⽂件系统**有⽤.
	unsigned int (*poll) (struct file*, struct poll_table_struct*);
	int (*ioctl) (struct inode*, struct file*, unsigned int, unsigned long);
	long (*unlocked_ioctl) (struct file*, unsigned int, unsigned long);
	long (*compat_ioctl) (struct file*, unsigned int, unsigned long);
	int (*mmap) (struct file*, struct vm_area_struct*);
	//mmap ⽤来请求将设备内存映射到进程的地址空间. 如果这个⽅法是 NULL, mmap 系统调⽤返
	回 - ENODEV.
		int (*open) (struct inode*, struct file*);
	//打开⼀个⽂件
	int (*flush) (struct file*, fl_owner_t id);
	//flush 操作在进程关闭它的设备⽂件描述符的拷⻉时调⽤;
	int (*release) (struct inode*, struct file*);
	//在⽂件结构被释放时引⽤这个操作. 如同 open, release 可以为 NULL.
	int (*fsync) (struct file*, struct dentry*, int datasync);
	//⽤⼾调⽤来刷新任何挂着的数据.
	int (*aio_fsync) (struct kiocb*, int datasync);
	int (*fasync) (int, struct file*, int);
	int (*lock) (struct file*, int, struct file_lock*);
	//lock ⽅法⽤来实现⽂件加锁; 加锁对常规⽂件是必不可少的特性, 但是设备驱动⼏乎从不实现
	它.
		ssize_t(*sendpage) (struct file*, struct page*, int, size_t, loff_t*,
			int);
	unsigned long (*get_unmapped_area)(struct file*, unsigned long, unsigned
		long, unsigned long, unsigned long);
	int (*check_flags)(int);
	int (*flock) (struct file*, int, struct file_lock*);
	ssize_t(*splice_write)(struct pipe_inode_info*, struct file*, loff_t*,
		size_t, unsigned int);
	ssize_t(*splice_read)(struct file*, loff_t*, struct pipe_inode_info*,
		size_t, unsigned int);
	int (*setlease)(struct file*, long, struct file_lock**);
};